package com.glsc.ngateway.platform.utils.report;

import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.oaflow.dto.SystemFlowRelationResultDto;
import com.glsc.ngateway.platform.utils.StringUtils;
import io.jsonwebtoken.lang.Collections;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author zhengyr
 * @date 2023/8/21-13:30
 * 报表导出枚举类（新功能启用）
 */
@Getter
@AllArgsConstructor
public enum ExportFileEnum {
    /**
     * 系统关联流程导出
     */
    SYSTEM_RELATION_FLOW(0, 0,
            "系统关联流程导出.xlsx",
            (ExportFileEnum.ExportBuilder<List>) data -> getDataAndTitleListFromDto(SystemFlowRelationResultDto.class, data),
            file -> ExcelUtil.getReader(file.getInputStream(), 0).read(0, 1, SystemFlowRelationResultDto.class)
    );

    /**
     * 开始行
     */
    private final int beginRow;
    /**
     * 开始列
     */
    private final int beginCol;
    /**
     * 导出文件名
     */
    private final String fileName;
    /**
     * 表头和属性map信息
     */
//    private final HashMap<String,List<String>> infoMap;
    /**
     * 表头
     */
//    private final List<String> title;
    /**
     * 导出数据build方法
     */
    private final ExportFileEnum.ExportBuilder exportBuilder;
    /**
     * 导入数据build方法
     */
    private final ExportFileEnum.ReadImportBuilder readImportBuilder;


    /**
     * 通过反射获取类及父类中带有@ExportProperty注解的index,根据index对属性进行排序，获得属性名数组和title数组
     */
    private static HashMap<String, List<String>> getTitlesAndProperties(Class<?> clz) {
        List<Class<?>> clzList = new ArrayList<>();
        while (clz != null) {
            clzList.add(clz);
            clz = clz.getSuperclass();
        }
        HashMap<String, List<String>> infoMap = new HashMap<>();
        List<String> title = new ArrayList<>();
        List<String> propertyList = new ArrayList<>();
        //倒序先将父节点的字段加入
        for (int i = clzList.size() - 1; i >= 0; i--) {
            clz = clzList.get(i);
            List<Field> list = Arrays.stream(clz.getDeclaredFields())
                    .filter(f -> f.isAnnotationPresent(ExcelProperty.class))
                    .sorted(Comparator.comparingInt(f -> f.getAnnotation(ExcelProperty.class).index()))
                    .map(f -> {
                        propertyList.add(f.getName());
                        title.add(f.getAnnotation(ExcelProperty.class).value()[0]);
                        return f;
                    })
                    .collect(Collectors.toList());
        }
        infoMap.put("titleList",title);
        infoMap.put("propertyList", propertyList);
        return infoMap;
    }
    /**
     *
     * @param data 是一个ExportDto类的对象
     * @return  hashMap包含两个值：二维数组dataList;一维数组titleList
     */
    static HashMap<String, List> getDataAndTitleListFromDto(Class<?> clz, List<?> data){
        HashMap<String, List> result = new HashMap<>();
        HashMap<String, List<String>> titlesAndProperties = getTitlesAndProperties(clz);
        result.put("titleList",titlesAndProperties.get("titleList"));
        if(Collections.isEmpty(data)){
            result.put("dataList", new ArrayList<>());
            return result;
        }
        List<String> propertyList = titlesAndProperties.get("propertyList");
        List<List<String>> dataList = data.stream().map(h -> {
            JSONObject jsonObj = JSONObject.parseObject(JSON.toJSONString(h));
            return propertyList.stream().map(o -> {
                Object value = jsonObj.get(o);
                //判断value是数组类型还是字符串或其他原始值类型
                boolean isArray = value instanceof Collection;
                if(isArray){
                    List<String> array = JSONObject.parseArray(JSONObject.toJSONString(value), String.class);
                    return StringUtils.getOrEmpty(array);
                }
                return StringUtils.getOrEmpty(String.valueOf(value));
            }).collect(Collectors.toList());
        }).collect(Collectors.toList());
        result.put("dataList", dataList);
        return result;
    }
    /**
     * 构建导出数据
     */
    public HashMap<String, List> export(List data) {
        return this.getExportBuilder().build(data);
    }

    /**
     * 读取导入数据
     */
    public <T> List<T> readImport(MultipartFile file) throws IOException {
        return this.getReadImportBuilder().read(file);
    }

    @FunctionalInterface
    private interface ExportBuilder<T> {
        //返回的map包含两个值：二维数组dataList;一维数组titleList
        HashMap<String, List> build(T data);
    }

    @FunctionalInterface
    private interface ReadImportBuilder<T> {
        List<T> read(MultipartFile file) throws IOException;
    }
}
